package com.example.java8.stream;

import com.example.entity.User;
import com.example.entity.UserHistory;
import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * stream api 中方法简单介绍及使用
 */
public class StreamApi {

    public static void main(String[] args) {
        // --------------  filter
//        filterTest();

        // --------------  distinct
//        distintTest();

        // --------------  map
//        mapTest();

        getGroupFirst();
    }

    /**
     * filter 过滤器
     * <p>
     *      filter方法用于过滤Stream中的元素，并用符合条件的元素生成一个新的Stream。
     */
    public static void filterTest() {

        /* 01 - 获取集合中包含"北京"的字符串 */
        List<String> list_01 = Lists.newArrayList("河南烩面", "河南焖面", "四川火锅", "北京卤煮", "北京烤鸭");
        list_01 = list_01.stream().filter(str -> str.contains("北京")).collect(Collectors.toList());
        System.out.println("list_01结果==: " + list_01);
    }

    /**
     * distinct 去重
     * <p>
     *      对stream中的元素使用给定的过滤函数进行过滤操作
     */
    public static void distintTest() {
        /* 01 - 将下列集合去重 */
        List<String> list_01 = Lists.newArrayList("河南", "河南", "四川", "北京", "北京");
        list_01 = list_01.stream().distinct().collect(Collectors.toList());
        System.out.println("list_01 去重后的结果==: " + list_01);
    }

    /**
     * map
     * <p>
     *  （1）把一种操作运算映射到Stream的每一个元素上，从而完成一个Stream到另一个Stream的转换，map方法接受的对象是Function接口，
     *       这个接口是一个函数式接口
     *  （2）对stream 中包含的元素使用给定的转换函数进行转换，新生成的stream只包含转换生成的元素。
     *  （3）这个方法还有三个常用的方法：mapToInt，mapToLong 和 mapToDouble
     *      mapToInt ： 比如mapToInt就是把原始Stream转换成一个新的Stream，这个新生成的Stream中的元素都是int类型
     */
    public static void mapTest() {
        /* 1、 获取Stream里每个数的平方的集合 并打印 */
        List<Integer> list_01 = Lists.newArrayList(1, 2, 3, 4, 5);
        list_01.stream().map(n -> n * n).forEach(System.out::println);

        /* 2、 获取实体类集合中每个实体的某个字段值放进另个集合中  */
        List<User> userList = StreamApi.getSomeUser();
        List<String> nameList = userList.stream()
                .map(User::getUserName)
                .collect(Collectors.toList());
        System.out.println(nameList);


    }

    /**
    * 分组，获取每组第一条数据
     * 需求：根据userId【用户ID】分组，更新时间降序排列，获取每组最新的第一条数据。
    */
    public static void  getGroupFirst() {

        /* 定义一个实体，提前模拟好根据“更新时间”降序排列 */
        List<UserHistory> userHistoryList = new ArrayList<>();
        userHistoryList.add(new UserHistory("1", "1", "搜索了海贼王","2019-03-15 13:33:25"));
        userHistoryList.add(new UserHistory("1", "1", "搜索了西游记","2019-03-13 02:14:25"));
        userHistoryList.add(new UserHistory("1", "1", "搜索了天气","2019-03-10 04:33:25"));

        userHistoryList.add(new UserHistory("1", "2", "搜索了火影","2019-03-12 08:06:25"));
        userHistoryList.add(new UserHistory("1", "2", "搜索了秦时明月","2019-03-13 02:14:25"));
        userHistoryList.add(new UserHistory("1", "2", "搜索了龙珠","2019-03-10 04:33:25"));

        /* 根据userId分组，并且获取每个分组的第一条数据 */
        Map<String, UserHistory> resultMap = userHistoryList.stream()
                .collect(Collectors.groupingBy(UserHistory::getUserId,
                        Collectors.collectingAndThen(Collectors.toList(), value->value.get(0))));
        // 遍历结果集
        for (Map.Entry<String, UserHistory> entry : resultMap.entrySet()) {
            String userId = entry.getKey();
            String searchContent =  entry.getValue().getSearchContent();
            String updateTime = entry.getValue().getUpdateTime();
            System.out.println("用户id===: " + userId + ", 搜索内容==: "+ searchContent + ", 更新时间==：" + updateTime);
        }


    }

    // 获取一些用户，返回集合
    public static List<User> getSomeUser() {
        List<User> userList = new ArrayList<>();
        userList.add(new User(1, "路飞", "lufei"));
        userList.add(new User(1, "索隆", "suolong"));
        userList.add(new User(1, "山治", "sanzhi"));
        userList.add(new User(1, "娜美", "namei"));
        return userList;
    }

}
